<?php

namespace Xin\Hyperf\Fortify\Facades;

use Hyperf\Context\ApplicationContext;
use Hyperf\Filesystem\FilesystemFactory;
use League\Flysystem\Config;
use League\Flysystem\Filesystem as LeagueFilesystem;
use League\Flysystem\PathNormalizer;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Xin\Support\Facade;
use Xin\Support\Reflect;

/**
 * @method static bool fileExists(string $location)
 * @method static bool directoryExists(string $location)
 * @method static bool has(string $location)
 * @method static void write(string $location, string $contents, array $config = [])
 * @method static void writeStream(string $location, $contents, array $config = [])
 * @method static string read(string $location)
 * @method static resource readStream(string $location)
 * @method static void delete(string $location)
 * @method static void deleteDirectory(string $location)
 * @method static void createDirectory(string $location, array $config = [])
 * @method static \League\Flysystem\DirectoryListing listContents(string $location, bool $deep = LeagueFilesystem::LIST_SHALLOW)
 * @method static void move(string $source, string $destination, array $config = [])
 * @method static void copy(string $source, string $destination, array $config = [])
 * @method static int lastModified(string $path)
 * @method static int fileSize(string $path)
 * @method static string mimeType(string $path)
 * @method static void setVisibility(string $path, string $visibility)
 * @method static string visibility(string $path)
 * @method static string publicUrl(string $path, array $config = [])
 * @method static string temporaryUrl(string $path, \DateTimeInterface $expiresAt, array $config = [])
 * @method static string checksum(string $path, array $config = [])
 */
class Filesystem extends Facade
{
    /**
     * @param string|null $disk
     * @return LeagueFilesystem
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function disk(string $disk = null): LeagueFilesystem
    {
        return self::getFacadeFactoryAccessor()->get($disk ?: 'local');
    }

    /**
     * 获取上传的真实路径
     * @param string $path
     * @param string|null $disk
     * @return string
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws \ReflectionException
     */
    public static function realpath(string $path, string $disk = null)
    {
        $filesystem = self::disk($disk);

        /** @var Config $config */
        $config = Reflect::getPropertyValue($filesystem, 'config');
        /** @var PathNormalizer $pathNormalizer */
        $pathNormalizer = Reflect::getPropertyValue($filesystem, 'pathNormalizer');

        $realPath = $config->get('root', $config->get('path', '')) . DIRECTORY_SEPARATOR . $path;

        return $pathNormalizer->normalizePath($realPath);
    }

    /**
     * @return LeagueFilesystem
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function getFacadeAccessor()
    {
        return self::disk();
    }

    /**
     * @return FilesystemFactory
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function getFacadeFactoryAccessor(): FilesystemFactory
    {
        return ApplicationContext::getContainer()->get(FilesystemFactory::class);
    }
}
